using System;
using System.IO;
using System.Collections.Generic;
using System.ComponentModel;
using System.Data;
using System.Drawing;
using System.Text;
using System.Windows.Forms;
using System.Net;
using System.Net.Mail;
using System.Net.Mime;

namespace CincinnatiLibraryRenew
{
    public partial class Form1 : Form
    {
        private string logFileName = null;
        private bool emailOnSuccess = false;
        private User user;
        public int count;
        private string currentHandler = "webBrowser1_DocumentCompleted";
        public Form1(User user)
        {
            this.user = user;
            InitializeComponent();
#if DEBUG
            //webBrowser1.DocumentCompleted -= webBrowser1_DocumentCompleted;
            //webBrowser1.DocumentCompleted += webBrowser1_SuccessPage;
            //webBrowser1.Navigate("file:///C:/Documents%20and%20Settings/Administrator/Desktop/13%20renewed%3b%203%20failed.html");
            webBrowser1.Navigate("http://catalog.cincinnatilibrary.org/uhtbin/cgisirsi/x/0/0/49");
#else
            webBrowser1.Navigate("http://catalog.cincinnatilibrary.org/uhtbin/cgisirsi/x/0/0/49");
#endif
        }

        private void webBrowser1_DocumentCompleted(object sender, WebBrowserDocumentCompletedEventArgs e)
        {
            timer1.Enabled = false;
            Text = webBrowser1.DocumentTitle;
            HtmlElement userID = webBrowser1.Document.GetElementById("user_id");
            if (userID == null)
            {
                if(webBrowser1.Url.AbsoluteUri!="http://catalog.cincinnatilibrary.org/")
                    Log("no element found on homepage with 'user_id' id");
                timer1.Enabled = true;
                return;
            }
            webBrowser1.DocumentCompleted -= webBrowser1_DocumentCompleted;
            webBrowser1.DocumentCompleted += webBrowser1_LoginCompleted;
            currentHandler = "webBrowser1_LoginCompleted";
            foreach (HtmlElement element in webBrowser1.Document.GetElementsByTagName("input"))
            {
                if (element.Name == "user_id")
                    element.InnerText = user.userid;
                else if (element.Name == "password")
                    element.InnerText = user.pin;
            }
            HtmlElement form = webBrowser1.Document.GetElementById("loginform");
            form.InvokeMember("submit");
            timer1.Enabled = true;
        }

        private void webBrowser1_LoginCompleted(object sender, WebBrowserDocumentCompletedEventArgs e)
        {
            timer1.Enabled = false;
            timer1.Enabled = true;
            HtmlElement userName = webBrowser1.Document.GetElementById("plch_login");
            if (userName==null || userName.GetElementsByTagName("form").Count > 0)
            {
                Log("Failed to login as " + user.userid);
                return;
            }
            try
            {
                if (userName.InnerText.StartsWith("you are logged in as"))
                    user.name = userName.InnerText.Substring(20).Trim();
                if (user.name.Contains(","))
                    user.name = user.name.Substring(user.name.IndexOf(",") + 1).Trim() + " " + user.name.Substring(0, user.name.IndexOf(",")).Trim();
            }
            catch (Exception ex)
            {
                Log("Exception thrown: " + ex.ToString());
            }
            webBrowser1.DocumentCompleted -= webBrowser1_LoginCompleted;
            //webBrowser1.DocumentCompleted += webBrowser1_MyAccountPage;
            //currentHandler = "webBrowser1_MyAccountPage";
            webBrowser1.DocumentCompleted += webBrowser1_RenewPage;
            currentHandler = "webBrowser1_RenewPage";
            foreach (HtmlElement a in webBrowser1.Document.GetElementsByTagName("a"))
            {
                if (a.InnerText == "My Account")
                {
                    webBrowser1.Navigate(a.GetAttribute("href"));
                    return;
                }
            }
            Log("No 'My Account' link found on page after logging in as " + user.name);
        }

        void webBrowser1_MyAccountPage(object sender, WebBrowserDocumentCompletedEventArgs e)
        {
            timer1.Enabled = false;
            timer1.Enabled = true;
            webBrowser1.DocumentCompleted -= webBrowser1_MyAccountPage;
            webBrowser1.DocumentCompleted += webBrowser1_RenewPage;
            currentHandler = "webBrowser1_RenewPage";
            foreach (HtmlElement a in webBrowser1.Document.GetElementsByTagName("a"))
            {
                if (a.InnerText == "Renew My Materials")
                {
                    webBrowser1.Navigate(a.GetAttribute("href"));
                    return;
                }
            }
            Log("No 'Renew My Materials' link found after clicking 'My Account' link");
        }

        void webBrowser1_RenewPage(object sender, WebBrowserDocumentCompletedEventArgs e)
        {
            timer1.Enabled = false;
            timer1.Enabled = true;
            webBrowser1.DocumentCompleted -= webBrowser1_RenewPage;
            webBrowser1.DocumentCompleted += webBrowser1_SuccessPage;
            currentHandler = "webBrowser1_SuccessPage";
            HtmlElement formRenewItems = webBrowser1.Document.GetElementById("renewitems");
            if (formRenewItems == null)
            {
                Log("No form found on renewal page named 'renewitems'");
                // check if catalog is undergoing maintenance
                HtmlElementCollection h1s = webBrowser1.Document.GetElementsByTagName("h1");
                if (h1s.Count > 0 && h1s[0].InnerHtml.Contains("Library Catalog is undergoing maintenance"))
                {
                    Log("Catalog is undergoing maintenance");
                    return;
                }
                else
                {
                    HtmlElementCollection divErrorMessages = webBrowser1.Document.GetElementsByTagName("div");
                    foreach (HtmlElement errorMessage in divErrorMessages)
                    {
                        if (errorMessage.OuterHtml.Contains("errorMessage") && !errorMessage.InnerHtml.Contains("errorMessage"))
                        {
                            Log("errorMessage: " + errorMessage.InnerText);
                            if (errorMessage.InnerText.Contains("User has nothing checked out"))
                            {
                                Close();
                                return;
                            }
                        }
                    }
                }
                return;
            }
            count = 0;
            int dueColumn = 4;
            int titleColumn = 2;
            foreach (HtmlElement tr in formRenewItems.GetElementsByTagName("tr"))
            {
                if(tr.InnerHtml.Contains("checkbox"))
                {
                    string date;
                    string title;
                    HtmlElementCollection cells = tr.GetElementsByTagName("td");
                    if (cells.Count <= dueColumn)
                        continue;
                    try
                    {
                        date = cells[dueColumn].InnerText;
                    }
                    catch (Exception)
                    {
                        continue;
                    }
                    title = cells[titleColumn].InnerText ;
                    //date = date.Substring(date.IndexOf("/") - 2);
                    //if (!Char.IsDigit(date, 0))
                    //    date = date.Substring(1);
                    date = date.Substring(0,date.LastIndexOf(','));
                    DateTime dt = Convert.ToDateTime(date);
#if WHOLEWEEK
                    if (dt <= DateTime.Today ||
                        ((int)DateTime.Today.DayOfWeek <=(int)DayOfWeek.Monday && dt.Subtract(DateTime.Today).Days < 7 &&
                            (!title.EndsWith("[videorecording]") || (dt - DateTime.Today).TotalDays < 3))))
#else
                    if (//(DateTime.Today.DayOfWeek == DayOfWeek.Sunday && dt.Subtract(DateTime.Today).Days <= 1) ||
                        dt <= DateTime.Today)
#endif
                    {
                        count++;
                        foreach (HtmlElement input in tr.GetElementsByTagName("input"))
                        {
                            if(input.GetAttribute("type")=="checkbox")
                            {
                                input.SetAttribute("checked", "true");
                                break;
                            }
                        }
                    }
                }
            }
            if (count > 0)
            {
                Log("Attempting to renew " + count.ToString() + " items.");
                formRenewItems.InvokeMember("submit");
            }
            else
            {
                Log("Nothing to renew for " + (user.name.Length > 0 ? user.name : user.userid) + "; exiting");
                Close();
            }
        }

        void webBrowser1_SuccessPage(object sender, WebBrowserDocumentCompletedEventArgs e)
        {
            timer1.Enabled = false;
            webBrowser1.DocumentCompleted -= webBrowser1_SuccessPage;
            currentHandler = "[no handler set]";
            foreach (HtmlElement h2 in webBrowser1.Document.GetElementsByTagName("h2"))
            {
                int index = h2.InnerText.IndexOf("item");
                if (index>0)
                {
                    string temp;
                    string emailText;
                    string numItems = h2.InnerText.Substring(0, index).Trim();
                    try
                    {
                        string itemsModifier = h2.InnerText.Substring(index + 5).Trim();
                        itemsModifier = itemsModifier.Substring(0, itemsModifier.IndexOf(' '));
                        if (itemsModifier == "failed")
                        {
                            bool emailThisTime = !emailOnSuccess;
                            emailText = "(" + user.name + "): " + h2.InnerText + ", out of " + count + " items that were attempted to be renewed.";
                            if (!emailOnSuccess)
                                Log(emailText);
                            emailText += "  Here's a list of the items that failed:\r\n\r\n";
                            foreach (HtmlElement tr in webBrowser1.Document.GetElementsByTagName("tr"))
                            {
                                if (tr.FirstChild.TagName.ToLower().Equals("th"))
                                {
                                    if (tr.FirstChild.InnerText.Trim() == "!")
                                    {
                                        string reason = tr.Children[1].InnerText.Trim().ToLower();
                                        if (reason != "renewal limit reached.")
                                        {
                                            emailText += "The one listed below, I will continue trying to renew every ten minutes.  I'll e-mail again if I get it renewed.\r\n";
                                            emailOnSuccess = true;
                                            timer2.Enabled = true;
                                        }
                                        emailText += tr.InnerText.Substring(1).Trim() + "\r\n\r\n";
                                    }
                                }
                            }
                            if (emailThisTime)
                            {
                                SendEmail(user.email, "attempted Library renewal", emailText);
                            }
                        }
                        else
                        {
                            Log(h2.InnerText);
                            if (emailOnSuccess) // there _was_ a success
                            {
                                emailOnSuccess = false;
                                emailText = "(" + user.name + "): " + h2.InnerText + ", out of " + count + " items that were attemped to be renewed.  Here's a list of everything.\r\n\r\n";
                                foreach (HtmlElement tr in webBrowser1.Document.GetElementsByTagName("tr"))
                                {
                                    if (tr.FirstChild.TagName.ToLower().Equals("th"))
                                    {
                                        string status = tr.FirstChild.InnerText.Trim();
                                        if (status == "!" || status == "ok")
                                        {
                                            string reason = tr.Children[1].InnerText.Trim().ToLower();
                                            if (status == "!" && reason != "renewal limit reached.")
                                            {
                                                emailText += "The one listed below, I will continue trying to renew every ten minutes.  I'll e-mail again if I get it renewed.\r\n";
                                                emailOnSuccess = true;
                                                timer2.Enabled = true;
                                            }
                                            emailText += tr.InnerText.Substring(status.Length).Trim() + "\r\n\r\n\r\n";
                                        }
                                    }
                                }
                                SendEmail(user.email, "successful Library renewal", emailText);
                                break;
                            }
                        }
                    }
                    catch (Exception ex)
                    {
                        temp = "Exception parsing '" + numItems + "' as an integer; " + count.ToString() + "item(s) were meant to be renewed.";
                        Log(temp);
                        SendEmail(user.email, "attempted Library renewal", temp);
                        Log(ex.ToString());
                    }
                }
            }
        }

        void Form1_FormClosing(object sender, FormClosingEventArgs e)
        {
            if (timer2.Enabled)
            {
                if(DialogResult.No == MessageBox.Show("I'm still doing stuff every ten minutes.  Are you sure you want to close the window?","Think about it",MessageBoxButtons.YesNo,MessageBoxIcon.Question))
                    e.Cancel = true;
            }
        }

        private string LogFileName
        {
            get
            {
                if(logFileName!=null)
                    return logFileName;
                else return logFileName = Directory.Exists(@"C:\CincinnatiLibraryRenew") ? @"C:\CincinnatiLibraryRenew\" + user.userid + ".log" :
                    (Directory.GetCurrentDirectory().ToLower().Contains("library")? Directory.GetCurrentDirectory() + "\\" + user.userid + ".log" : Directory.GetCurrentDirectory().Substring(0,1) + @":\CincinnatiLibraryRenew.log");
            }
        }

        public void Log(string text)
        {
            using (StreamWriter sw = new StreamWriter(LogFileName,true))
            {
                sw.WriteLine(DateTime.Now.ToShortDateString() + " - " + DateTime.Now.ToLongTimeString() + " - " + text);
            }
        }

        private void timer1_Tick(object sender, EventArgs e)
        {
            timer1.Enabled = false;
            Log("after 30 seconds, " + currentHandler + " was never called.  Strange, that.  It's likely some sort of bug.");
            webBrowser1.DocumentCompleted -= webBrowser1_DocumentCompleted;
            webBrowser1.DocumentCompleted -= webBrowser1_LoginCompleted;
            webBrowser1.DocumentCompleted -= webBrowser1_MyAccountPage;
            webBrowser1.DocumentCompleted -= webBrowser1_RenewPage;
            webBrowser1.DocumentCompleted -= webBrowser1_SuccessPage;
            webBrowser1.DocumentCompleted += webBrowser1_DocumentCompleted;
            webBrowser1.Navigate("http://catalog.cincinnatilibrary.org");
        }

        private void SendEmail(string to, string subject, string body)
        {
            if (to == null || to.Length == 0)
                return;
            MailMessage msg = new MailMessage();
            msg.To.Add(to);
            msg.From = new MailAddress("librarysender@gmail.com", "Library Sender", System.Text.Encoding.UTF8);
            msg.Subject = subject;
            msg.SubjectEncoding = System.Text.Encoding.UTF8;
            msg.Body = body;
            msg.BodyEncoding = System.Text.Encoding.UTF8;
            msg.IsBodyHtml = false;
            msg.Priority = MailPriority.High;

            //Add the Creddentials
            SmtpClient client = new SmtpClient();
            client.Credentials = new System.Net.NetworkCredential("librarysender@gmail.com", "inconsequential");
            client.Port = 587;
            client.Host = "smtp.gmail.com";
            client.EnableSsl = true;
            client.SendCompleted += new SendCompletedEventHandler(client_SendCompleted);
            object userState = msg;
            try
            {
                //you can also call client.Send(msg)
                client.SendAsync(msg, userState);
            }
            catch (System.Net.Mail.SmtpException ex)
            {
                MessageBox.Show(ex.Message, "Send Mail Error");
            }
        }

        void client_SendCompleted(object sender, AsyncCompletedEventArgs e)
        {
            //TODO: possibly do something here.
        }

        private void timer2_Tick(object sender, EventArgs e)
        {
            timer2.Enabled = false;
            webBrowser1.DocumentCompleted -= webBrowser1_DocumentCompleted;
            webBrowser1.DocumentCompleted -= webBrowser1_LoginCompleted;
            webBrowser1.DocumentCompleted -= webBrowser1_MyAccountPage;
            webBrowser1.DocumentCompleted -= webBrowser1_RenewPage;
            webBrowser1.DocumentCompleted -= webBrowser1_SuccessPage;
            webBrowser1.DocumentCompleted += webBrowser1_DocumentCompleted;
            webBrowser1.Navigate("http://catalog.cincinnatilibrary.org");
        }
    }
}